<template>
    <view class="easy-loadimage" :id="uid">
        <image class="origin-img" :data-src="imageSrc" :src="imageSrc" :mode="mode" v-if="loadImg&&!isLoadError"
               v-show="showImg"
               :class="{'no-transition':!openTransition,'show-transition':showTransition&&openTransition}"
               @load="handleImgLoad" @error="handleImgError" @tap="clickCurrentImg"></image>
        <view class="loadfail-img" v-else-if="isLoadError"></view>
        <view :class="['loading-img',loadingMode]" v-show="!showImg&&!isLoadError"></view>
    </view>
</template>
<script>function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    })
}

export default {
    props: {
        imageSrc: {type: String,},
        mode: {type: String,},
        scrollTop: {type: Number,},
        loadingMode: {type: String, default: 'looming-gray'},
        openTransition: {type: Boolean, default: true,},
        viewHeight: {
            type: Number, default() {
                return uni.getSystemInfoSync().windowHeight;
            }
        }
    }, watch: {
        scrollTop(val) {
            this.onScroll(val)
        }
    }, data() {
        return {uid: '', loadImg: false, showImg: false, isLoadError: false, showTransition: false,}
    }, methods: {
        clickCurrentImg(e) {
            this.$emit('previewImage', e.target.dataset.src)
        }, init() {
            this.uid = 'uid-' + generateUUID();
            this.$nextTick(this.onScroll)
        }, handleImgLoad(e) {
            this.showImg = true;
            setTimeout(() => {
                this.showTransition = true
            }, 50)
        }, handleImgError(e) {
            this.isLoadError = true;
        }, onScroll(scrollTop) {
            if (this.loadImg || this.isLoadError) return;
            const id = this.uid;
            const query = uni.createSelectorQuery().in(this);
            query.select('#' + id).boundingClientRect(data => {
                if (!data) return;
                if (data.top - this.viewHeight < 0) {
                    this.loadImg = true;
                }
            }).exec()
        },
    }, mounted() {
        this.init()
    }
}</script>
<style scoped>image {
    will-change: transform
}

image.origin-img {
    width: 100%;
    height: 100%;
    opacity: 0.3;
}

image.origin-img.show-transition {
    transition: opacity 1.2s;
    opacity: 1;
}

image.origin-img.no-transition {
    opacity: 1;
}

.loadfail-img {
    height: 100%;
    background: url('~@/static/easy-loadimage/loadfail.png') no-repeat center;
    background-size: 50%;
}

.loading-img {
    height: 100%;
}

.spin-circle {
    background: url('~@/static/easy-loadimage/loading.gif') no-repeat center;
    background-size: 100 rpx;
}

.looming-gray {
    animation: looming-gray 1s infinite linear;
    background-color: #e3e3e3;
}

@keyframes looming-gray {
    0% {
        background-color: #e3e3e3aa;
    }
    50% {
        background-color: #e3e3e3;
    }
    100% {
        background-color: #e3e3e3aa;
    }
}

.skeleton-1 {
    background-color: #e3e3e3;
    background-image: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 80%);
    background-size: 100 rpx 100%;
    background-repeat: repeat-y;
    background-position: 0 0;
    animation: skeleton-1 .6s infinite;
}

@keyframes skeleton-1 {
    to {
        background-position: 200% 0;
    }
}

.skeleton-2 {
    background-image: linear-gradient(-90deg, #fefefe 0%, #e6e6e6 50%, #fefefe 100%);
    background-size: 400% 400%;
    background-position: 0 0;
    animation: skeleton-2 1.2s ease-in-out infinite;
}

@keyframes skeleton-2 {
    to {
        background-position: -135% 0;
    }
}</style>
